The sample program AddReferenceTrack.c illustrates how you can modify a movie to use a modifier track for a sprite's image data. The sample program prompts the user for a movie that contains a single sprite track. Then, it adds a track from a second movie to the original movie as a modifier track. The modifier track overrides the image data for a selected image index.
Listing 3-13 shows the first part of the main function of the sample program. It performs the following tasks:
OSErr err;
short movieResID = 0, resFref, resID = 0, resRefNum;
StandardFileReply reply;
SFTypeList types;
Movie m;
FSSpec fss;
Movie movieB;
long origTrackCount;
// prompt for a movie containing a sprite track and load it
types[0] = MovieFileType;
StandardGetFilePreview (nil, 1, types, &reply);
if (!reply.sfGood) return;
err = OpenMovieFile (&reply.sfFile, &resFref, fsRdPerm);
if (err) return;
err = NewMovieFromFile (&m, resFref, &movieResID, (StringPtr)nil,
newMovieActive, ni);
if (err) return;
CloseMovieFile (resFref);
// get the number of tracks
origTrackCount = GetMovieTrackCount (m);
// load the movie to be used as a modifier track
FSMakeFSSpec (reply.sfFile.vRefNum, reply.sfFile.parID, "\pAdd Me",
&fss);
err = OpenMovieFile (&fss, &resFref, fsRdPerm);
if (err) return;
err = NewMovieFromFile (&movieB, resFref, &resID, (StringPtr)nil, 0,
nil);
if (err) return;
CloseMovieFile (resFref);
Once the two movies have been loaded, the sample program retrieves the first track, which is the sprite track, from the original movie, and sets the selection to the start of the movie ( Listing 3-14 ). The sample program iterates through all the tracks in the modifier movie, disposing of all non-video tracks.
Next, the sample program calls AddMovieSelection to add the modifier track to the original movie. Finally, the sample program calls AddTrackReference to associate the modifier track with the sprite track it will modify. AddTrackReference returns an index of the added reference in the referenceIndex variable.
Listing 14 Adding the modifier track to the movie
Movie m;
TimeValue oldDuration;
Movie movieB;
long i, origTrackCount, referenceIndex;
Track newTrack, spriteTrack;
// get the first track in original movie and position at the start
spriteTrack = GetMovieIndTrack (m, 1);
SetMovieSelection (m, 0 ,0);
// remove all tracks except video in modifier movie
for (i = 1; i <= GetMovieTrackCount (movieB); i++)
{
Track t = GetMovieIndTrack (movieB, i);
OSType aType;
GetMediaHandlerDescription (GetTrackMedia(t), &aType, nil, nil);
if (aType != VideoMediaType)
{
DisposeMovieTrack (t);
i--;
}
}
// add the modifier track to original movie
oldDuration = GetMovieDuration (m);
AddMovieSelection (m, movieB);
DisposeMovie (movieB);
// truncate the movie to the length of the original track
DeleteMovieSegment (m, oldDuration,
GetMovieDuration (m) - oldDuration);
// associate the modifier track with the original sprite track
newTrack = GetMovieIndTrack (m, origTrackCount + 1);
AddTrackReference (spriteTrack, newTrack, kTrackModifierReference,
&referenceIndex);
Besides adding a reference to the modifier track, the sample program must update the sprite media's input map to describe how the modifier track should be interpreted by the sprite track. The sample program performs the following tasks ( Listing 3-15 ):
Listing 15 Updating the media's input map
#define kImageIndexToOverride 1
Movie m, movieB;
long referenceIndex, imageIndexToOverride;
Track spriteTrack;
QTAtomContainer inputMap;
QTAtom inputAtom;
OSType inputType;
Media spriteMedia;
// get the sprite media's input map
spriteMedia = GetTrackMedia (spriteTrack);
GetMediaInputMap (spriteMedia, &inputMap);
// add an atom for a modifier track
QTInsertChild (inputMap, kParentAtomIsContainer,
kTrackModifierInput, referenceIndex, 0, 0, nil, &inputAtom);
// add a child atom to specify the input type
inputType = kTrackModifierTypeImage;
QTInsertChild (inputMap, inputAtom, kTrackModifierType, 1, 0,
sizeof(inputType), &inputType, nil);
// add a second child atom to specify index of image to override
imageIndexToOverride = kImageIndexToOverride;
QTInsertChild (inputMap, inputAtom, kSpritePropertyImageIndex, 1, 0,
sizeof(imageIndexToOverride), &imageIndexToOverride, nil);
// update the sprite media's input map
SetMediaInputMap (spriteMedia, inputMap);
QTDisposeAtomContainer (inputMap);
Once the media's input map has been updated, the application can save the movie.
| Previous | Chapter Contents | Chapter Top | Next |